10-4 Du夆jkG洏帣Vk

上一小節所描述的方法是一個一般性的方法,因為它把對所有參數都是一視同仁,全部視為非線性參數。但是我們還可以進一步改良,也就是將線性與非線性參數分開,各用不同的方法來處理。以上例而言,數學模型為

$$ y= a_1 e^{\lambda_1 x} + a_2 e^{\lambda_2 x} $$

其中 $a_1$ 及 $a_2$ 為線性參數,$\lambda_2$ 及 $\lambda_2$ 為非線性參數,因此我們可以對它們分開處理,如下:

此方法的好處是:最小平方法能夠在非線性參數($\lambda_2$ 及 $\lambda_2$)固定的情況下,一次找到最好的線性參數($a_1$ 及 $a_2$)的值,因為搜尋空間的維度由 4($a_1$、$a_2$、$\lambda_1$、$\lambda_2$),降為 2($\lambda_1$、$\lambda_2$),最佳化會更有效率。

如果要使用上述混成(Hybrid)的方法,函式 errorMeasure1 須改寫成 errorMeasure2,如下:

Example 1: 10-曲線擬合與迴歸分析/errorMeasure2.mfunction squaredError = errorMeasure2(lambda, data) if nargin<1; return; end x = data(:,1); y = data(:,2); A = [exp(lambda(1)*x) exp(lambda(2)*x)]; a = A\y; y2 = a(1)*exp(lambda(1)*x)+a(2)*exp(lambda(2)*x); squaredError = sum((y-y2).^2);

其中 lambda 是非線性參數向量,只包含 $\lambda_2$ 及 $\lambda_2$,data 仍是觀察到的資料點,a 則是利用最小平方法算出的最佳線性參數向量(即 $a_1$ 及 $a_2$ 隨傳入的 $\lambda_2$ 及 $\lambda_2$ 而變),而傳回的 squareError 仍是總平方誤差。此函數和 errorMeasure1 的最大不同在於我們只須傳入線性參數($\lambda_2$ 及 $\lambda_2$),最佳線性參數($a_1$ 及 $a_2$)的值則在函式中由最小平方法決定。

欲用此混成法求出誤差平方和的最小值,可輸入如下:

Example 2: 10-曲線擬合與迴歸分析/nonlinearFit02.mload data.txt lambda0 = [0 0]; tic lambda = fminsearch(@(x)errorMeasure2(x, data), lambda0); fprintf('計算時間 = %g\n', toc); x = data(:, 1); y = data(:, 2); A = [exp(lambda(1)*x) exp(lambda(2)*x)]; a = A\y; y2 = A*a; plot(x, y, 'ro', x, y2, 'b-'); legend('Sample data', 'Regression curve'); fprintf('誤差平方和 = %d\n', sum((y-y2).^2));[Warning: Rank deficient, rank = 1, tol = 2.136826e-14.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('errorMeasure2', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m', 6)" style="font-weight:bold">errorMeasure2</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m',6,0)">line 6</a>) In %4287963446>@(x)errorMeasure2(x,data) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('fminsearch', 'C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p', 190)" style="font-weight:bold">fminsearch</a> (<a href="matlab: opentoline('C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p',190,0)">line 190</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('nonlinearFit02', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m', 4)" style="font-weight:bold">nonlinearFit02</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m',4,0)">line 4</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'd:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'd:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)] [Warning: Rank deficient, rank = 1, tol = 2.137360e-14.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('errorMeasure2', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m', 6)" style="font-weight:bold">errorMeasure2</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m',6,0)">line 6</a>) In %4287963446>@(x)errorMeasure2(x,data) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('fminsearch', 'C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p', 309)" style="font-weight:bold">fminsearch</a> (<a href="matlab: opentoline('C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p',309,0)">line 309</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('nonlinearFit02', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m', 4)" style="font-weight:bold">nonlinearFit02</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m',4,0)">line 4</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'd:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'd:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)] [Warning: Rank deficient, rank = 1, tol = 2.136960e-14.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('errorMeasure2', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m', 6)" style="font-weight:bold">errorMeasure2</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m',6,0)">line 6</a>) In %4287963446>@(x)errorMeasure2(x,data) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('fminsearch', 'C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p', 350)" style="font-weight:bold">fminsearch</a> (<a href="matlab: opentoline('C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p',350,0)">line 350</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('nonlinearFit02', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m', 4)" style="font-weight:bold">nonlinearFit02</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m',4,0)">line 4</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'd:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'd:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)] [Warning: Rank deficient, rank = 1, tol = 2.137093e-14.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('errorMeasure2', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m', 6)" style="font-weight:bold">errorMeasure2</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\errorMeasure2.m',6,0)">line 6</a>) In %4287963446>@(x)errorMeasure2(x,data) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('fminsearch', 'C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p', 365)" style="font-weight:bold">fminsearch</a> (<a href="matlab: opentoline('C:\Program Files\MATLAB\R2015a\toolbox\matlab\optimfun\fminsearch.p',365,0)">line 365</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('nonlinearFit02', 'D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m', 4)" style="font-weight:bold">nonlinearFit02</a> (<a href="matlab: opentoline('D:\users\jang\books\matlabProgramming4guru\example\10-曲線擬合與迴歸分析\nonlinearFit02.m',4,0)">line 4</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'd:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'd:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)] 計算時間 = 0.153491 誤差平方和 = 1.477226e-01

此種混成法可以產生較低的誤差平方和,同時所需的計算時間也比較短。

Hint
  • 在上例中,MATLAB 會產生警告訊息,這是由於在最佳化的過程中,可能出現 $\mathbf{A}$ 的 rank 小於其行數,導致 $a=\mathbf{A}$\$y$ 出現 「Rank deficient 」的警告訊息。但只要最後我們檢視擬合圖形,能得到滿意結果,即可忽略這最佳化過程所產生的暫時警告訊息。
  • 欲檢視上述迴歸過程的動畫顯示,可在 MATLAB 指令視窗下輸入 fitdemo。


MATLAB程式設計:進階篇